home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 August: Tool Chest / Dev.CD Aug 98 TC.toast / Tool Chest / Testing & Debugging / Mac OS Development Toolkit / Automation Essentials 2.3.0 / Host Automation Folder / Clouseau libs / Report.Lib < prev    next >
Encoding:
Text File  |  1998-03-19  |  55.0 KB  |  1,754 lines  |  [TEXT/MPS ]

  1. #########################################################################
  2. #########################################################################
  3. ##                     Copyright © Apple Computer, Inc. 1990-1997
  4. ##                                All rights reserved
  5. #########################################################################
  6. #########################################################################
  7. #    
  8. #    Library:        Report.lib
  9. #
  10. #    Version:        2.1.4
  11. #    
  12. #    Description:    Tasks for reporting to the VU notebook; timing.
  13. #    
  14. #    Contains:
  15. #        ROpenTest()
  16. #        RCloseTest()
  17. #        RResult()
  18. #        RAddResult()
  19. #        RStatus()
  20. #        RError()
  21. #        RIncomplete()
  22. #        RXStatus()
  23. #        RXError()
  24. #        RXIncomplete()
  25. #        RDumpState()
  26. #        RPushVerbosity()
  27. #        RPopVerbosity()
  28. #        RPrint()
  29. #        R_Indent()             (internal task)
  30. #        R_NestIn()             (internal task)
  31. #        R_NestOut()         (internal task)
  32. #        R_BeVerbose()         (internal task)
  33. #        _takeScreenShot()     (internal task)
  34. #        midstr()
  35. #        substr()
  36. #        list_to_str()
  37. #        str_to_list()
  38. #        timed_out()
  39. #        get_end_time()
  40. #        timer()
  41. #        time_list()
  42. #        time_cmp()
  43. #        time_neg()
  44. #        time_add()
  45. #        time_sub()
  46. #        time_str()
  47. #        GetCheckSums()
  48. #        ComputerAidedSE()
  49. #        rSetCAidedSE()
  50. #    
  51. #    History:
  52. #        Date:        By:                Changes:
  53. #        08/02/90    Alan Liu        Creation
  54. #        03/04/92    Jason Marsh        Incorporated v_level for use with Clouseau.lib.
  55. #        05/15/92    Jason Marsh        Created summaries, rResult, rAddStatus, CAidedSE, etc.
  56. #        02/22/94    SBR    Reformatted according to standards; R_BeVerbose mod
  57. #        06/29/94    SBR    get_end_time mod
  58. #        07/07/94    SBR    rewrote get_end_time mod for speed
  59. #        09/04/95    SBR                updated header for Radar 1273927
  60. #        09/27/96    BRL/MSO/SBR        Updated copyright header
  61. #                                    Use SPEC exception handling method (ExceptionHandling.lib)
  62. #        01/21/97    SBR                Deleted older exception code and comments.
  63. #    
  64. #########################################################################
  65. #########################################################################
  66.  
  67. Libraries    "VUAid.tool",
  68.             "ExceptionHandling.lib";
  69.  
  70.  
  71. #########################################################################
  72. #    task                    ROpenTest(name, v_level)
  73. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  74. #    Description:    Report the beginning of a test.
  75. #    Parameters:        name:        string to log
  76. #                    v_level:    logs according to RBeVerbose
  77. #    Returns:        Nothing
  78. #    Examples:        ROpenTest("Close Window tests");
  79. #    Assumptions:    None
  80. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  81. #    History:
  82. #        8/2/90        Alan Liu    Creation
  83. #        06/30/93    SBR            clear gAddResult
  84. #        09/27/96    BRL/MSO        Added SPEC exception handling
  85. #########################################################################
  86. task     ROpenTest(name, v_level:=1)
  87. begin
  88.     global r_error_stack;        
  89.     global r_error_count;
  90.     global r_passed_count;
  91.     global r_incomplete_count;
  92.     
  93.     global gAddResult := {};
  94.     
  95.     if isUndefined(global r_test_stack)
  96.     begin
  97.         r_test_stack := {};
  98.         R_NestIn();
  99.         global r_error_stack := {};        
  100.         global r_error_count := 0;
  101.         global r_passed_count := 0;
  102.         global r_incomplete_count := 0;
  103.     end;
  104.         
  105.     save_trace := trace(false);
  106.  
  107.     r_test_stack := insert({name, _Match([time])}, 1, r_test_stack);
  108.     
  109.     if r_error_stack <> {}
  110.         r_error_stack := replace({r_error_count + r_error_stack[1][1],
  111.                                 r_passed_count + r_error_stack[1][2],
  112.                                 r_incomplete_count + r_error_stack[1][3]}, 1, r_error_stack);
  113.         
  114.     r_error_stack := insert({0,0,0}, 1, r_error_stack);
  115.     r_error_count := 0;        
  116.     r_passed_count := 0;
  117.     r_incomplete_count := 0;
  118.     
  119.     if R_BeVerbose(v_level)
  120.     begin
  121.         R_Indent(v_level);
  122.         println "Begin {name}";
  123.     end;
  124.     R_NestIn();
  125.  
  126.     trace(save_trace);
  127. end;
  128.  
  129.  
  130. #########################################################################
  131. #    task                    RCloseTest(v_level, summary)
  132. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  133. #    Description:    Report the finishing of a test.
  134. #    Parameters:        v_level:        logs according to RBeVerbose
  135. #                    summary:        print a result summary for this block
  136. #    Returns:        Nothing
  137. #    Examples:        RCloseTest();
  138. #    Assumptions:    None
  139. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  140. #    History:
  141. #        8/2/90        Alan Liu    Creation
  142. #        09/27/96    BRL/MSO        Added SPEC exception handling
  143. #########################################################################
  144. task    RCloseTest(v_level:=1, summary := false)
  145. begin
  146.     global r_test_stack, r_error_stack;
  147.     global r_error_count, r_passed_count, r_incomplete_count;
  148.     
  149.     save_trace := trace(false);
  150.  
  151.     test_failed := r_error_count + r_error_stack[1][1];
  152.     test_passed := r_passed_count + r_error_stack[1][2];
  153.     test_incomplete := r_incomplete_count + r_error_stack[1][3];
  154.     
  155.     r_error_stack := remove(1, r_error_stack);
  156.     if r_error_stack <> {} 
  157.         r_error_stack := replace({test_failed + r_error_stack[1][1],
  158.                                 test_passed + r_error_stack[1][2],
  159.                                 test_incomplete + r_error_stack[1][3]}, 1, r_error_stack);
  160.         
  161.     test := r_test_stack[1];
  162.     r_test_stack := remove(1, r_test_stack);
  163.     
  164.     name := test[1];
  165.     gap := time_str(time_sub(test[2], _Match([time])));
  166.  
  167.     R_NestOut();
  168.     if R_BeVerbose(v_level)
  169.     begin
  170.         if test_failed = 0
  171.         begin
  172.             temp:= "no";
  173.             if test_incomplete <> 0
  174.             begin
  175.                 print "•Inc•";
  176.                 R_Indent(v_level - 1);
  177.             end;
  178.             else R_Indent(v_level);
  179.         end;
  180.         else begin
  181.             print "•Failed•";
  182.             temp := "{test_failed}";
  183.             R_Indent(v_level - 2);
  184.         end;
  185.     end;
  186.     
  187.     total := test_passed + test_failed;
  188.     println "End {name}: {temp} Errors out of {total} tests  ({gap})";
  189.     
  190.     if (r_test_stack = {})
  191.     begin
  192.         R_NestOut();
  193.         R_NestOut();
  194.     end;
  195.     
  196.     if (r_test_stack = {} or summary) 
  197.     begin
  198.         println;
  199.         R_Indent(v_level); println "Summary of ", name, ":";
  200.         R_Indent(v_level); println "∂t", total + test_incomplete, " tests run";
  201.         R_Indent(v_level); println "∂t", test_passed, " tests passed";
  202.         R_Indent(v_level); println "∂t", test_failed, " tests failed";
  203.         R_Indent(v_level); println "∂t", test_incomplete, " tests incomplete";
  204.         R_Indent(v_level); println "∂t", "execution time: ", gap;
  205.         println;
  206.     end;
  207.         
  208.     r_error_count := 0;
  209.     r_passed_count := 0;
  210.     r_incomplete_count := 0;
  211.     
  212.     trace(save_trace);
  213. end;
  214.  
  215.  
  216.  
  217. #########################################################################
  218. #    task    RResult(tResult, testName, expected, actual, takeScrShot, CAidedSE, v_level)
  219. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  220. #    Description:    Report the result of a test.  This is the primary
  221. #                    communication the script has with the log.  Update
  222. #                    the test summary.  If expected <> actual report them.
  223. #                    If takeScrShot is true, do so.
  224. #    Parameters:        tResult:         true and 'pass' for passed
  225. #                                    false and 'fail' for error
  226. #                                    'incomplete' for incomplete
  227. #                    testName:         the string to log
  228. #                    expected:         expected value for a test
  229. #                    actual:          actual value for a test. 
  230. #                    takeScrShot:      if true, do the routine to take a screen shot.
  231. #                    CAidedSE:          Print out the result in testN format, instead of errors
  232. #                    v_level:         logs according to RBeVerbose
  233. #    Returns:        Nothing
  234. #    Examples:        rResult(actual = expected,"balloon for {testName}", expected, actual);
  235. #    Assumptions:    None
  236. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  237. #    History:
  238. #        5/15/92    Jason Marsh        Created
  239. #########################################################################
  240. task    RResult(tResult := "pass", testName := "", expected:= undefined, actual:= undefined, takeScrShot:= false, CAidedSE:= false, v_level:= 2)
  241. begin
  242.     if IsUndefined(global gCAidedSEEnabled)
  243.         gCAidedSEEnabled := false;
  244.     
  245.     if gCAidedSEEnabled
  246.         return ComputerAidedSE(CAidedSE);
  247.         
  248.     if typeOf(tResult) <> 'string'
  249.         if tResult 
  250.             tResult := "pass";
  251.         else tResult := "fail";
  252.         
  253.     if tResult = "incomplete"
  254.     begin
  255.         if IsUndefined(global r_incomplete_count)
  256.             r_incomplete_count := 1; 
  257.         else r_incomplete_count := r_incomplete_count +1;        
  258.         RIncomplete("Incomplete: " + testName);
  259.         if takeScrShot
  260.             _takeScreenShot();
  261.     end;
  262.     else if (tResult = "pass")
  263.     begin
  264.         if IsUndefined(global r_passed_count)
  265.             r_passed_count := 1; 
  266.         else r_passed_count := r_passed_count +1;        
  267.         RStatus("Verified: " + testName);
  268.     end;
  269.     else begin
  270.         if IsUndefined(global r_error_count) 
  271.             r_error_count := 1; 
  272.         else r_error_count := r_error_count +1;        
  273.         RError("Failed: " + testName);
  274.         if (not isUndefined(expected) or not isUndefined(actual)) and R_BeVerbose(3) 
  275.         begin
  276.             RPrint ("    -" , 2, 3);
  277.             if not isUndefined(expected)
  278.                 print "   expected: ", expected, "   ";
  279.             if not isUndefined(actual)
  280.                 print "   actual: ", actual;
  281.             println;
  282.         end;
  283.         if takeScrShot 
  284.             _takeScreenShot();
  285.     end;
  286.     
  287.     if isUndefined(global gAddResult) 
  288.         gAddResult := {};
  289.     for i:= 1 to card gAddResult 
  290.     begin
  291.         temp := gAddResult[i];
  292.         if R_BeVerbose(3)
  293.             if typeOf(temp) = 'list' 
  294.             begin
  295.                 RPrint ("    -" , 2, 3);
  296.                 for each j in temp
  297.                     print j;
  298.                 println;
  299.             end;
  300.             else RPrint("    - {temp}", 2, 8, true);
  301.     end;
  302.         
  303.     gAddResult := {};
  304. end;
  305.  
  306.  
  307. #########################################################################
  308. #    task        RAddResult(str, expected, actual)
  309. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  310. #    Description:    Add to the result stack of a test, to be printed below
  311. #                    the RResult statement. If expected <> actual, print out
  312. #                    this information as well.
  313. #    Parameters:        str:        the str to log
  314. #                    expected:    the expected value for a test
  315. #                    actual:        the actual value of a test
  316. #    Returns:        Nothing
  317. #    Examples:        RAddResult("Verified: all radiobuttons in correct state.");
  318. #    Assumptions:    None
  319. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  320. #    History:
  321. #        5/15/92    Jason Marsh        Created
  322. #########################################################################
  323. task    RAddResult(str := "", expected:= undefined, actual:= undefined)
  324. begin
  325.     if isUndefined(global gAddResult) 
  326.         gAddResult:= {};
  327.     
  328.     if str <> ""
  329.         gAddResult := gAddResult + {str};
  330.     
  331.     if (not isUndefined(expected) or not isUndefined(actual)) 
  332.     begin
  333.         EAPrint := {};
  334.         if not isUndefined(expected)
  335.             EAPrint := {"   expected: ", expected, "   "};
  336.         if not isUndefined(actual)
  337.             EAPrint := EAPrint + {"   actual: ", actual};
  338.         gAddResult := gAddResult + {EAPrint};
  339.     end;
  340.     
  341.     return true;
  342. end;
  343.  
  344.  
  345. #########################################################################
  346. #    task                    RStatus(str, v_level)
  347. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  348. #    Description:    Report the status of a test.
  349. #    Parameters:        str:        the str to log
  350. #                    v_level:    logs according to RBeVerbose
  351. #    Returns:        This ALWAYS returns true, enabling it to be used in a
  352. #                    'return' statement with ease and elegance.
  353. #    Examples:        if (select_descriptor([menuitem t:"Control Panels" m:1]) <> error)
  354. #                        return RStatus("open_control_panel: successful");
  355. #    Assumptions:    None
  356. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  357. #    History:
  358. #        05/15/92    Jason Marsh    Created
  359. #        04/10/93    SBR            Changed RPrint call to use auto-cr parameter
  360. #        02/19/94    SBR            If v_level = -1 send output to RAddResult
  361. #########################################################################
  362. task    RStatus(str, v_level:= 2)
  363. begin
  364.     save_trace := trace(false);
  365.     
  366.     if (R_BeVerbose(v_level)) 
  367.         RPrint(": {str}", v_level, 2, true);
  368.     else if v_level = -1
  369.         RAddResult(str);
  370.         
  371.     trace(save_trace);
  372.     return true;                        #no error
  373. end;
  374.  
  375. #########################################################################
  376. #    task                    RError(str, v_level)
  377. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  378. #    Description:    Report a VU-level error in a test.
  379. #    Parameters:        str:        the str to log
  380. #                    v_level:    logs according to RBeVerbose
  381. #    Returns:        This ALWAYS returns false, enabling it to be used in a
  382. #                    'return' statement with ease and elegance.
  383. #    Examples:        if (error) return RError("this_task: didn't work",,450, 451);
  384. #    Assumptions:    None
  385. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  386. #    History:
  387. #        05/15/92    Jason Marsh    Created
  388. #        04/10/93    SBR            Changed RPrint call to use auto-cr parameter
  389. #        02/19/94    SBR            If v_level = -1 send output to RAddResult
  390. #########################################################################
  391. task    RError(str, v_level:= 1)
  392. begin
  393.     save_trace := trace(false);
  394.         
  395.     if (R_BeVerbose(v_level)) begin
  396.         print "•E•";
  397.         RPrint("• {str}", v_level, 7, true);
  398.     end;
  399.     else if v_level = -1
  400.         RAddResult("•E• {str}");
  401.     
  402.     trace(save_trace);
  403.     return false;                        #error
  404. end;
  405.  
  406.  
  407. #########################################################################
  408. #    task                    RIncomplete(str, v_level)
  409. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  410. #    Description:    Report an incomplete result in a test.
  411. #    Parameters:        str:        the str to log
  412. #                    v_level:    logs according to RBeVerbose
  413. #    Returns:        This ALWAYS returns false, enabling it to be used in a
  414. #                    'return' statement with ease and elegance.
  415. #    Examples:        if (error) return RIncomplete("this_task: didn't complete");
  416. #    Assumptions:    None
  417. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  418. #    History:
  419. #        05/15/92    Jason Marsh    Created
  420. #        04/10/93    SBR            Changed RPrint call to use auto-cr parameter
  421. #        02/19/94    SBR            If v_level = -1 send output to RAddResult
  422. #########################################################################
  423. task    RIncomplete(str, v_level := 1)
  424. begin
  425.     save_trace := trace(false);
  426.         
  427.     if (R_BeVerbose(v_level)) 
  428.     begin
  429.         print "•I•";
  430.         RPrint("! {str}", v_level, 7, true);
  431.     end;
  432.     else if v_level = -1
  433.         RAddResult("•I• {str}");
  434.     
  435.     trace(save_trace);
  436.     return false;                        #error
  437. end;
  438.  
  439.  
  440. #########################################################################
  441. #    task                    RXStatus(v_level)
  442. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  443. #    Description:    Report the status of a test.  This only takes care of
  444. #                    proper indentation, etc.  It should be used with a
  445. #                    println statement.  These are neccesary because VU 
  446. #                    does not easily pass [descriptor] and list[] information
  447. #                    to tasks.
  448. #    Parameters:        v_level:    logs according to RBeVerbose
  449. #    Returns:        Returns according to RBeVerbose.
  450. #    Examples:        if RXStatus(v_level) println "type_keys: typing ", key_list; 
  451. #    Assumptions:    None
  452. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  453. #    History:
  454. #        5/15/92    Jason Marsh        Created
  455. #########################################################################
  456. task    RXStatus(v_level := 2)
  457. begin
  458.     save_trace := trace(false);
  459.     
  460.     if (R_BeVerbose(v_level)) 
  461.     begin
  462.         R_Indent(v_level);
  463.         print ": ";
  464.         retVal := true;
  465.     end;
  466.     else retVal := false;
  467.  
  468.     trace(save_trace);
  469.     return retVal;
  470. end;
  471.  
  472.  
  473. #########################################################################
  474. #    task                    RXError(v_level)
  475. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  476. #    Description:    Report a VU-level error in a test.  This only takes care of
  477. #                    proper indentation, etc.  It should be used with a
  478. #                    println statement.  These are neccesary because VU 
  479. #                    does not easily pass [descriptor] and list[] information
  480. #                    to tasks.
  481. #    Parameters:        v_level:    logs according to RBeVerbose
  482. #    Returns:        Returns according to RBeVerbose.
  483. #    Examples:        if RXError(v_level) println "select_descriptor: Unable to find '",itemDesc,"'";
  484. #    Assumptions:    None
  485. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  486. #    History:
  487. #        5/15/92    Jason Marsh        Created
  488. #########################################################################
  489. task    RXError(v_level:=1)
  490. begin
  491.     save_trace := trace(false);
  492.  
  493.     if (R_BeVerbose(v_level)) 
  494.     begin
  495.         print "•E•";
  496.         R_Indent(v_level);
  497.         print "• ";
  498.         retVal := true;
  499.     end;
  500.     else retVal := false;
  501.  
  502.     trace(save_trace);
  503.     return retVal;
  504. end;
  505.  
  506.  
  507. #########################################################################
  508. #    task                    RXIncomplete(v_level)
  509. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  510. #    Description:    Report an incomplete result in a test.  This only takes care of
  511. #                    proper indentation, etc.  It should be used with a
  512. #                    println statement.  These are neccesary because VU 
  513. #                    does not easily pass [descriptor] and list[] information
  514. #                    to tasks.
  515. #    Parameters:        v_level:    logs according to RBeVerbose
  516. #    Returns:        Returns according to RBeVerbose.
  517. #    Examples:        if RXIncomplete(v_level) println "select_descriptor: Unable to find '",itemDesc,"'";
  518. #    Assumptions:    None
  519. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  520. #    History:
  521. #        5/15/92    Jason Marsh        Created
  522. #########################################################################
  523. task    RXIncomplete(v_level:=1)
  524. begin
  525.     save_trace := trace(false);
  526.     
  527.     if (R_BeVerbose(v_level)) 
  528.     begin
  529.         print "•I•";
  530.         R_Indent(v_level);
  531.         print "! ";
  532.         retVal := true;
  533.     end;
  534.     else retVal := false;
  535.     
  536.     trace(save_trace);
  537.     return retVal;                        #error
  538. end;
  539.  
  540.  
  541. #########################################################################
  542. #    task                    RDumpState(desc_type, v_level)
  543. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  544. #    Description:    Show general information about the state of the target
  545. #                    machine. We show the current application, the frontmost
  546. #                    window, and current menus.
  547. #    Parameters:        desc_type:    List available descriptors on the target of
  548. #                                this type.  Can be any VU descriptor type,
  549. #                                such as 'button'.
  550. #                    v_level:    logs according to RBeVerbose
  551. #    Returns:        Returns according to RBeVerbose.
  552. #    Examples:        RDumpState('menuItem');
  553. #    Assumptions:    None
  554. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  555. #    History:
  556. #        8/2/90        Alan Liu    Creation
  557. #        09/27/96    BRL/MSO        Added SPEC exception handling
  558. #########################################################################
  559. task    RDumpState(desc_type := '', v_level:=5)
  560. begin
  561.     save_trace := trace(false);
  562.  
  563.     try begin
  564.         # many raw matches happen in this section
  565.         # they're all covered by the above try statement
  566.         if (R_BeVerbose(v_level))
  567.         begin
  568.             if desc_type
  569.             begin
  570.                 dList := 'UNKNOWN';
  571.                 if desc_type = 'menu' ; #Do nothing
  572.                 else if desc_type = 'menuItem' match [menuItem t:$dList];
  573.                 else if desc_type = 'button' match [button t:$dList];
  574.                 else if desc_type = 'window' match [window t:$dList];
  575.                 else if desc_type = 'radioButton' match [radioButton t:$dList];
  576.                 else if desc_type = 'checkBox' match [checkBox t:$dList];
  577.                 else if desc_type = 'popUp' match [popUp t:$dList];
  578.                 else if desc_type = 'screen' dList := match [screen];
  579.                 else if desc_type = 'scrollBar' match [scrollBar t:$dList];
  580.                 else RError("RDumpState: I don't know what a ∂"{desc_type}∂" is.", v_level);
  581.                 RXError(v_level);
  582.                 println "RDumpState: Available {desc_type}s: ", dList;
  583.                 RXError(v_level);
  584.                 print   "            ";
  585.             end;
  586.             else begin
  587.                 RXError(v_level);
  588.                 print   "RDumpState: ";
  589.             end;
  590.             println "Application: ", match [application];
  591.             RXError(v_level);
  592.             println "            Front window: ", match [window o:1];
  593.             match [menu t:$dList];
  594.             RXError(v_level);
  595.             println "            Available menus: ", dList;
  596.             retVal := true;
  597.         end;
  598.         else
  599.             retVal := false;
  600.     end;
  601.     catch theError
  602.     begin
  603.         trace(save_trace);
  604.         ExceptionDispatcher(theError,,{"RDumpState() match section", {desc_type, v_level}});
  605.     end;
  606.  
  607.     trace(save_trace);
  608.     return retVal;
  609. end;
  610.  
  611.  
  612. #########################################################################
  613. #    task                    RPushVerbosity(v_level)
  614. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  615. #    Description:    Set the global verbosity.  This is used in a stack
  616. #                    format with RPopVerbosity().
  617. #    Parameters:        desc_type:    List available descriptors on the target of
  618. #                                this type.  Can be any VU descriptor type,
  619. #                                such as 'button'.
  620. #                    v_level:    0;     #no output except for Not-Tested-List
  621. #                                1;    #only Begin/End tests, Errors, Not-Tested-List and summaries
  622. #                                2;    #run-time output, without specifying multiple verifications
  623. #                                3;     #run-time output, with multiple verifications
  624. #                                4;     #scripter's debugging-level output
  625. #                                5;     #Clouseau-libs level debugging-output
  626. #    Returns:        Nothing.
  627. #    Examples:        RPushVerbosity(4);
  628. #    Assumptions:    None
  629. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  630. #    History:
  631. #        8/2/90    Alan Liu        Creation
  632. #########################################################################
  633. task RPushVerbosity(v_level := 2)
  634. begin
  635.     global r_verbosity, r_verbosity_stack;
  636.  
  637.     if isUndefined(r_verbosity) 
  638.         r_verbosity := 1;
  639.     if isUndefined(r_verbosity_stack) 
  640.         r_verbosity_stack := {};
  641.  
  642.     r_verbosity_stack := insert(r_verbosity, 1, r_verbosity_stack);
  643.     r_verbosity := v_level;
  644. end;
  645.  
  646. #########################################################################
  647. #    task                    RPopVerbosity()
  648. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  649. #    Description:    Revert to the previous verbosity setting.  Popping
  650. #                    an empty stack sets the verbosity to 1.
  651. #    Parameters:        none
  652. #    Returns:        Nothing.
  653. #    Examples:        RPopVerbosity();
  654. #    Assumptions:    None
  655. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  656. #    History:
  657. #        8/2/90    Alan Liu        Creation
  658. #########################################################################
  659. task RPopVerbosity()
  660. begin
  661.     global r_verbosity, r_verbosity_stack;
  662.  
  663.     if isUndefined(r_verbosity_stack) 
  664.         r_verbosity_stack := {};
  665.  
  666.     if (card r_verbosity_stack) > 0 
  667.     begin
  668.         r_verbosity := r_verbosity_stack[1];
  669.         r_verbosity_stack := remove(1, r_verbosity_stack);
  670.     end;
  671.     else r_verbosity := 1;
  672. end;
  673.  
  674. #########################################################################
  675. #    task    RPrint(str, v_level, nest, auto_cr, word_wrap, tabSize)
  676. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  677. #    Description:    Print a string out, using the current indent, and
  678. #                    wrapping if longer than word_wrap characters.
  679. #    Parameters:        str:        string to print to log
  680. #                    v_level:    only used to determine indentation.
  681. #                    nest:        specifies the extra indentation for lines
  682. #                                after the first line.
  683. #                    auto_cr:    true to add carriage return
  684. #                    word_wrap:    Attempt to do a smart word wrap. The only
  685. #                                recognized whitespace character is a space.
  686. #                                If true but not integer, defaults to 100.
  687. #                    tabSize:    number of spaces for a tab
  688. #    Returns:        Nothing.
  689. #    Examples:        RPrint(logString, v_level, 4, true);
  690. #    Assumptions:    None
  691. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  692. #    History:
  693. #        8/2/90        Alan Liu    Creation
  694. #        04/11/92    SBR        removed '†' code, put auto_cr before word_wrap
  695. #        04/11/92    SBR        Changed word_wrap to integer, added tabSize
  696. #########################################################################
  697. task    RPrint(str, v_level:= 2, nest := 0, auto_cr := false, 
  698.                     word_wrap := 100, tabSize := 4)
  699. begin
  700.     global r_nesting;    if isUndefined(r_nesting) r_nesting := 0;
  701.     
  702.     strLength := card str;
  703.     
  704.     if word_wrap                 #for compatibility with old word_wrap
  705.         if (typeOf(word_wrap) <> integer or word_wrap = 1) 
  706.         begin
  707.             word_wrap := 100;        #for compatibility with old word_wrap
  708.             maxLineLength := word_wrap - tabs * r_nesting;
  709.         end;
  710.         else maxLineLength := 1000;
  711.     done := false;
  712.     currentPosition := 1;
  713.     first_line := true;
  714.     while not done 
  715.     begin
  716.         R_Indent(v_level);
  717.         if not first_line 
  718.             for i := 1 to nest print " ";
  719.         if (word_wrap and (currentPosition + maxLineLength <= strLength)) 
  720.         begin
  721.             blank_position := currentPosition + maxLineLength - 1;
  722.             if blank_position > strLength 
  723.                 blank_position := strLength;
  724.             while str[blank_position] <> ' ' and blank_position > currentPosition
  725.                 blank_position := blank_position - 1;
  726.             if (blank_position > currentPosition) 
  727.             begin
  728.                 print midstr(str, currentPosition, blank_position - currentPosition);
  729.                 currentPosition := blank_position + 1;    (*Skip the blank*)
  730.             end;
  731.             else begin
  732.                 print midstr(str, currentPosition, maxLineLength);
  733.                 currentPosition := currentPosition + maxLineLength;
  734.             end;
  735.         end;
  736.         else begin
  737.             if currentPosition = 1        #print a short line fast
  738.                 print str;
  739.             else                        #print the rest of a wrapped line
  740.                 print midstr(str, currentPosition, maxLineLength);
  741.             currentPosition := currentPosition + maxLineLength;
  742.         end;
  743.  
  744.         if currentPosition <= strLength 
  745.             println; 
  746.         else done := true;
  747.         
  748.         if first_line 
  749.         begin
  750.             first_line := false;
  751.             maxLineLength := maxLineLength - nest;
  752.         end;
  753.     end;
  754.     if auto_cr 
  755.         println;
  756. end;
  757.  
  758. #########################################################################
  759. #########                    Internal Tasks                        #########
  760. #########################################################################
  761.  
  762. #########################################################################
  763. #    task            R_Indent(v_level)
  764. #    Description:    Indent, based on the current level of nesting, or if
  765. #                    v_level passed, according to v_level requested.
  766. #    Parameters:        v_level:    Amount to indent
  767. #    Returns:        Nothing
  768. #    History:
  769. #        ???        ???        Created
  770. #########################################################################
  771. task    R_Indent(v_level := "")
  772. begin
  773.     global r_nesting;    if isUndefined(r_nesting) r_nesting := 0;
  774.     if not (v_level = "")                     # if v_level passed, and it is 2
  775.         temp := r_nesting + v_level - 1;    #    indent another time
  776.                                         
  777.     for i := 1 to temp 
  778.         print "∂t";        
  779. end;
  780.  
  781. #########################################################################
  782. #    task            R_NestIn()
  783. #    Description:    Increase the level of nesting.
  784. #    Parameters:        None
  785. #    Returns:        Nothing
  786. #    History:
  787. #        ???        ???        Created
  788. #########################################################################
  789. task    R_NestIn()
  790. begin
  791.     global r_nesting;
  792.     
  793.     if isUndefined(r_nesting) 
  794.         r_nesting := 0;
  795.  
  796.     r_nesting := r_nesting + 1;
  797. end;
  798.  
  799. #########################################################################
  800. #    task            R_NestOut()
  801. #    Description:    Decrease the level of nesting.
  802. #    Parameters:        None
  803. #    Returns:        Nothing
  804. #    History:
  805. #        ???        ???        Created
  806. #########################################################################
  807. task    R_NestOut()
  808. begin
  809.     global r_nesting;    
  810.     
  811.     if isUndefined(r_nesting) 
  812.         r_nesting := 0;
  813.  
  814.     r_nesting := r_nesting - 1;
  815.     if (r_nesting < 0) 
  816.         r_nesting := 0;
  817. end;
  818.  
  819. #########################################################################
  820. #    task            R_BeVerbose(v_level)
  821. #    Description:    Determine whether printing should occur, given the
  822. #                    current verbosity setting compared to the v_level of
  823. #                    this specific message.
  824. #    Parameters:        v_level:    Verbosity of this message. The higher the
  825. #                                number, the less likely the global verbosity
  826. #                                level will be that high, and the less likely
  827. #                                the string will print to the VU Notebook.
  828. #                                If v_level is zero or less, or if the global
  829. #                                verbosity level is zero, return false.
  830. #    Returns:        true if printing should occur, false if not
  831. #    History:
  832. #        ???            ???        Created
  833. #        02/22/94    SBR        Changed v_level = 0 to v_level <= 0
  834. #########################################################################
  835. task    R_BeVerbose(v_level:=5)
  836. begin
  837.     global r_verbosity;    
  838.     if isUndefined(r_verbosity) 
  839.         r_verbosity := 1;
  840.     if r_verbosity = 0 or v_level <= 0     
  841.         return false;
  842.     if r_verbosity < v_level             
  843.         return false;
  844.     else return true;
  845. end;
  846.  
  847. #########################################################################
  848. #    task            _takeScreenShot(v_level)
  849. #    Description:    Take a screen shot without using VUAid.Lib. Used by RResult.
  850. #    Parameters:        v_level:    verbosity of log output
  851. #    Returns:        true if printing should occur, false if not
  852. #    History:
  853. #        5/15/92        Jason Marsh    Created
  854. #        09/27/96    BRL/MSO        Added SPEC exception handling
  855. #########################################################################
  856. task    _takeScreenShot(v_level := 2)    
  857. begin
  858.     _PressKey({ shiftKey, commandKey});                #Screen shot fKey
  859.     _Type({'3'});
  860.     _ReleaseKey({ shiftKey, commandKey});
  861.     wait(10);                                        #Screen Shots can be slow
  862.     
  863.     timeStamp := time_str(time_list());
  864.     result := VUAid2("FindFolder", "boot");
  865.     if result[1] = 0 
  866.     begin
  867.         VUAid2("Rename", result[2] + ":Picture 1", result[2] + ":ScreenShot@" + timeStamp);
  868.         RAddResult("screenShot taken and named: ScreenShot@{timeStamp}");
  869.     end;
  870.     else
  871.         RAddResult("screenShot taken but not renamed properly!");
  872. end;
  873.  
  874. #########################################################################
  875. #########                    String manipulation tasks            #########
  876. #########################################################################
  877.  
  878. #########################################################################
  879. #    task            midstr(str, pos, len)
  880. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  881. #    Description:    This task returns a string from the middle of the
  882. #                    given string.  A pos of 1 refers to the first character.
  883. #                    It returns the empty string if pos is outside str.
  884. #    Parameters:        str:        String to examine
  885. #                    pos:        Position of subString
  886. #                    len:        Length of subString
  887. #    Returns:        subString
  888. #    Examples:        midstr("abcde", 3, 999);    #returns "cde"
  889. #    Assumptions:    None
  890. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  891. #    History:
  892. #        ???        ???        Created
  893. #########################################################################
  894. task    midstr(str, pos, len)
  895. begin
  896.     save_trace := trace(false);
  897.     lstr := card str;
  898.     mid := "";
  899.     if pos = 1 and len >= lstr
  900.         mid := str;
  901.     else if (pos > 0 and pos <= lstr) 
  902.     begin
  903.         limit := pos + len - 1;
  904.         if limit > lstr 
  905.             limit := lstr;
  906.         for i := pos to limit 
  907.             mid := mid + str[i];
  908.     end;
  909.     trace(save_trace);
  910.     return mid;
  911. end;
  912.  
  913.         
  914. #########################################################################
  915. #    task            substr(bigstr, littlestr)
  916. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  917. #    Description:    This task returns the leftmost position at which the
  918. #                    substring {littlestr} matches the string {bigstr}, or
  919. #                    0 if there is no match.
  920. #    Parameters:        bigstr:        String to examine
  921. #                    littlestr:    string to match
  922. #    Returns:        subString
  923. #    Examples:        substr("abcdbc", "bc");    #returns 2
  924. #    Assumptions:    None
  925. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  926. #    History:
  927. #        ???        ???        Created
  928. #########################################################################
  929. task    substr(bigstr, littlestr)
  930. begin
  931.     save_trace := trace(false);
  932.     if not (bigstr ~= /≈{littlestr}≈/) 
  933.     begin                                
  934.         trace(save_trace);                    # Modified here to restore trace setting
  935.         return 0;
  936.     end;
  937.     
  938.     blen := card bigstr;
  939.     llen := card littlestr;
  940.     
  941.     if (blen < llen)                         # littlestr larger than bigstr
  942.     begin
  943.         trace(save_trace);                    # Modified here to restore trace setting
  944.         return 0;
  945.     end;
  946.     
  947.     for bpos := 0 to (blen - llen) 
  948.     begin
  949.         gotit := true;
  950.         for lpos := 1 to llen 
  951.         begin
  952.             if littlestr[lpos] <> bigstr[lpos + bpos] 
  953.             begin
  954.                 gotit := false;
  955.                 lpos := llen;
  956.             end;
  957.         end;
  958.         if gotit 
  959.         begin
  960.             trace(save_trace);                # Modified here to restore trace setting
  961.             return (bpos + 1);
  962.         end;
  963.     end;
  964.  
  965.     trace(save_trace);
  966.     return 0;
  967. end;
  968.  
  969. #########################################################################
  970. #    task            list_to_str(theList, delimiter)
  971. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  972. #    Description:    This task returns a usable string from a list. Delimiter
  973. #                    specifies the separator. This task will work only on
  974. #                    lists of numbers or strings, not lists of lists, 
  975. #                    descriptors, etc.
  976. #    Parameters:        theList:    List to convert
  977. #                    delimiter:    String to append between list items
  978. #    Returns:        resulting string
  979. #    Examples:        list_to_str({"a", "b", "c"}, " ");    #returns "a b c"
  980. #    Assumptions:    None
  981. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  982. #    History:
  983. #        ???        ???        Created
  984. #    12/03/93    SBR        Fixed bug: theList was named MyList in some places
  985. #    12/03/93    SBR        Fixed bug: list is now 'list'
  986. #########################################################################
  987. task    list_to_str(theList := {}, delimiter := " ")
  988. begin
  989.     if typeOf(theList) <> 'list' or card theList < 1
  990.         return("");
  991.     temp:= theList[1];
  992.     result := "{temp}";
  993.     for i := 2 to card theList
  994.     begin
  995.         temp := theList[i];
  996.         result := result + delimiter + "{temp}";
  997.     end;
  998.     return result;
  999. end;
  1000.  
  1001.  
  1002. #########################################################################
  1003. #    task            str_to_list(str, delimiter)
  1004. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1005. #    Description:    This task returns a usable string from a list. Delimiter
  1006. #                    specifies the separator. This task will work only on
  1007. #                    lists of numbers or strings, not lists of lists, 
  1008. #                    descriptors, etc.
  1009. #    Parameters:        str:        String to parse
  1010. #                    delimiter:    String that delimits items
  1011. #    Returns:        resulting list
  1012. #    Examples:        str_to_list({"a,b,c"}, ",");    #returns ("a","b","c"}
  1013. #    Assumptions:    None
  1014. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1015. #    History:
  1016. #        ???        ???        Created
  1017. #########################################################################
  1018. task    str_to_list(str, delimiter := " ")
  1019. begin
  1020.     MyList := {};
  1021.     done := false;
  1022.     while not done 
  1023.     begin
  1024.         Space:= substr(str, delimiter);
  1025.         if space = 0 
  1026.         begin
  1027.             MyList := MyList + {StrToNum(str)};
  1028.             done := true;
  1029.         end;
  1030.         else begin
  1031.             MyList := MyList + {StrToNum(midstr(str, 1, Space -1))};
  1032.             str := midstr(str, Space + 1, 999);
  1033.         end;
  1034.     end;
  1035.     return MyList;
  1036. end;
  1037.  
  1038.  
  1039.         
  1040. ##############################################################################
  1041. #########                NEW INTERVAL TIMING TASKS                    ##########
  1042. #########    These two tasks are specifically designed for routines that need to 
  1043. #########    do some activity for a limited amount of time, and periodically 
  1044. #########    check if the time limit has passed. They are optimized to be as 
  1045. #########    fast as possible, instead of doing generic "timer math". The
  1046. #########    maximum interval allowed is slightly less than one day.
  1047. #########    
  1048. #########    To initialize the timer, call get_end_time(), giving it the interval 
  1049. #########    between now until the time limit. It will return a list containing 
  1050. #########    the end time. This structure is similar to a time list, but it has
  1051. #########    been optimized for quickly checking intervals of less than a minute.
  1052. #########    
  1053. #########    To check if the time limit has passed, call timed_out(), giving it 
  1054. #########    the list from get_end_time(). It will return true if the time limit 
  1055. #########    has passed, or false if there is still time left.
  1056. ##############################################################################
  1057.  
  1058. #########################################################################
  1059. #    task            timed_out(endTime)
  1060. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1061. #    Description:    Checks to see if the current time is after the specified 
  1062. #                    endTime. This is for intervals less than a day and is 
  1063. #                    optimized for speed. The basic idea is, do all the math 
  1064. #                    once at the beginning. Then rather than carry around an 
  1065. #                    interval, carry the actual time of expiration. To check 
  1066. #                    if the time has expired, just do a compare, and almost 
  1067. #                    no calculations. Use the get_end_time() task to calculate 
  1068. #                    the proper endTime given the start time and an interval.
  1069. #                    This task is designed for speed and does not log status.
  1070. #    Parameters:        endTime: {ss,mins,dd,mm,yyyy} where all fields are equal
  1071. #                        to time descriptor traits except for mins, in
  1072. #                        the form 0 <= mins <= 1338. There is no hours field,
  1073. #                        because the minutes field can hold an entire day.
  1074. #    Returns:        false if current time is less than endTime
  1075. #                    true if current time is greater than endTime,
  1076. #                        i.e. the process has timed out
  1077. #    Assumptions:    For any interval you are checking, there is only one 
  1078. #                    crossing of 12 midnight, i.e. interval < 24 hrs. 
  1079. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1080. #    History:
  1081. #        05/22/94    SBR        Created
  1082. #        02/20/95    SBR        Added trace hiding
  1083. #        09/27/96    BRL/MSO    Added SPEC exception handling
  1084. #########################################################################
  1085. task timed_out(endTime := {0,0,0,0,0})
  1086. begin
  1087.     saveTrace := trace(false);
  1088.     
  1089.     try begin
  1090.         try 
  1091.             match [time y:?curYear m:?curMonth d:?curDay h:?curMinute s:?curSecond];
  1092.         catch theError
  1093.             ExceptionDispatcher(theError,,{"timed_out() match", {endTime}});
  1094.             
  1095.         curMinute := (curMinute/100) * 60 + (curMinute mod 100);    #1438 min = 23:58:00
  1096.         endSecond := endTime[1];
  1097.         endMinute := endTime[2];
  1098.         
  1099.         if curMinute = endMinute     # only occurs if elapsed <= 59 seconds 
  1100.         begin                        # i.e. can only occur on the same day
  1101.             if curSecond < endSecond
  1102.                 throw false;
  1103.             else throw true;
  1104.         end;
  1105.         
  1106.         # After this point all we need is one clue to determine if we are before
  1107.         # or after the endTime.
  1108.         
  1109.         endDay := endTime[3];
  1110.         if curDay = endDay
  1111.         begin
  1112.             if curMinute < endMinute
  1113.                 throw false;
  1114.             else throw true;
  1115.         end;
  1116.                 
  1117.         endMonth := endTime[4];
  1118.         if curMonth = endMonth
  1119.         begin
  1120.             if curDay < endDay
  1121.                 throw false;
  1122.             else throw true;
  1123.         end;
  1124.                 
  1125.         endYear := endTime[5];
  1126.         if curYear = endYear
  1127.         begin
  1128.             if curMonth < endMonth
  1129.                 throw false;
  1130.             else throw true;
  1131.         end;
  1132.         
  1133.         if curYear < endYear
  1134.             throw false;
  1135.         else throw true;
  1136.     end;
  1137.     catch theReturnValue
  1138.     begin
  1139.         if typeOf(theReturnValue) = 'symbol'        # we expect a Boolean type
  1140.         begin
  1141.             trace(saveTrace);
  1142.             return theReturnValue;
  1143.         end;
  1144.         else
  1145.         begin
  1146.             RIncomplete( "timed_out: caught unexpected error: {theReturnValue}; throwing",1);
  1147.             trace(saveTrace);
  1148.             throw theReturnValue;
  1149.         end;
  1150.     end;
  1151. end;
  1152.  
  1153. ##############################################################################
  1154. #        task  get_end_time(interval)
  1155. ##############################################################################
  1156. #    Description:    Use the get_end_time() task to calculate the proper 
  1157. #                    endTime. The start time is whenever the task is called.
  1158. #                    This task is designed for speed and does not log status.
  1159. #    Parameters:    
  1160. #        interval:    list: {ss,mins} where 
  1161. #                            0 <= ss <= 59
  1162. #                            0 <= mins <= 1338        1338 = 24 hrs - 2 min
  1163. #              or:    integer: ss where 
  1164. #                            0 <= ss <= 32706        32706 = 32767 - 61 = {7,544}
  1165. #                            sum of ss and curSecond must be < VU 2.0.1 max integer
  1166. #            CAUTION:    The total interval must be < 23 hrs, 59 min,
  1167. #                        because the optimizations depend on it.
  1168. #    Returns:        {ss,mins,dd,mm,yyyy} where all fields are equal
  1169. #                    to time descriptor traits except for mins, in
  1170. #                    the form 0 <= mins <= 1338. There is no hours field,
  1171. #                    because the mins field can hold an entire day.
  1172. #    Assumptions:    For any interval you are checking, there is only one 
  1173. #                    crossing of midnight. This is always true using legal 
  1174. #                    values for the interval.
  1175. #    
  1176. #    Date        Initials    Change
  1177. #    05/22/94    SBR            Created
  1178. #    06/07/94    SBR            Added 'ifs' for carries; allow integer interval
  1179. #    06/29/94    SBR            Return a value for next larger item even if no carry
  1180. #                            because timed_out needs it. Others remain undefined.
  1181. #    07/06/94    SBR            Decreased max ss from 80339 to 32706 to avoid VU 2.0.1
  1182. #                            integer overflow when we add intervalSec to curSec.
  1183. #    02/20/95    SBR            Added trace hiding
  1184. #    09/27/96    BRL/MSO        Added SPEC exception handling
  1185. ##############################################################################
  1186. task get_end_time(interval := {10,0})
  1187. begin
  1188.     saveTrace := trace(false);
  1189.     
  1190.     try 
  1191.         match [time y:?curYear m:?curMonth d:?curDay h:?curMinute s:?curSecond];
  1192.     catch theError
  1193.         ExceptionDispatcher(theError,,{"get_end_time() match", {interval}});
  1194.         
  1195.     curMinute := (curMinute/100) * 60 + (curMinute mod 100);
  1196.     
  1197.     if typeOf(interval) = 'list'
  1198.     begin
  1199.         intervalSec := interval[1];
  1200.         intervalMin := interval[2];
  1201.     end;
  1202.     else begin                            #typeOf(interval) = 'integer'
  1203.         intervalSec := interval;
  1204.         intervalMin := 0;
  1205.     end;
  1206.     
  1207.     endSecond := curSecond + intervalSec;
  1208.     carry := 0;
  1209.     if endSecond >= 60 
  1210.     begin
  1211.         carry := endSecond / 60;
  1212.         endSecond := endSecond mod 60;
  1213.     end;
  1214.     
  1215.     if carry 
  1216.     begin                                    # carry into next minute
  1217.         endMinute := curMinute + intervalMin + carry;
  1218.         carry := 0;
  1219.         if endMinute >= 1440
  1220.         begin
  1221.             carry := 1;
  1222.             endMinute := endMinute - 1440;
  1223.         end;
  1224.     
  1225.         if carry 
  1226.         begin                                # carry into next day
  1227.             endDay := curDay + carry;
  1228.             carry := 0;
  1229.         
  1230.             len := {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}[curMonth];
  1231.             if (curMonth = 2) and ((curYear mod 4) = 0) len := len + 1;
  1232.         
  1233.             if endDay > len 
  1234.             begin
  1235.                 carry := 1;
  1236.                 endDay := endDay - len;
  1237.             end;
  1238.         
  1239.             if carry 
  1240.             begin                            # carry into next month
  1241.                 endMonth := curMonth + carry;
  1242.                 carry := 0;
  1243.                 if endMonth > 12 
  1244.                 begin
  1245.                     carry := 1;
  1246.                     endMonth := endMonth - 12;
  1247.                 end;
  1248.             
  1249.                 if carry                            # carry into next year
  1250.                     endYear := endYear + carry;
  1251.                 else 
  1252.                     endYear := curYear;                # 06/29 SBR: year value if no carry
  1253.             end;
  1254.             else 
  1255.                 endMonth := curMonth;                # 06/29 SBR: month value if no carry
  1256.         end;
  1257.         else 
  1258.             endDay := curDay;                        # 06/29 SBR: day value if no carry
  1259.     end;
  1260.     else 
  1261.         endMinute := curMinute;                        # 06/29 SBR: minute value if no carry
  1262.  
  1263.     trace(saveTrace);
  1264.     
  1265.     return {endSecond, endMinute, endDay, endMonth, endYear};
  1266. end;
  1267.  
  1268.  
  1269.  
  1270. #########################################################################
  1271. #########                    TIME TASKS                            #########
  1272. #########    These tasks manipulate 'time' data structures,        #########
  1273. #########    which are lists consisting of:                        #########
  1274. #########        {sec, min, hour, day, month, year, sign}        #########
  1275. #########    The sign may be +1 or -1.                            #########
  1276. #########################################################################
  1277.  
  1278. #########################################################################
  1279. #    task            timer(func)
  1280. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1281. #    Description:    This task implements a timer.
  1282. #    Parameters:        func:
  1283. #                        'reset':    Reset the timer to zero.
  1284. #                        'read':        Read the current elapsed time since
  1285. #                                    'reset' was called.
  1286. #    Returns:        resulting time list if func = 'read'
  1287. #    Examples:        timer('reset);
  1288. #                    elapsedTime := timer('read');
  1289. #    Assumptions:    None
  1290. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1291. #    History:
  1292. #        ???            ???        Created
  1293. #        09/27/96    BRL/MSO    Added SPEC exception handling
  1294. #########################################################################
  1295. task    timer(func := 'null')
  1296. begin
  1297.     global timer_start;
  1298.  
  1299.     if (func = 'reset')
  1300.         timer_start := _Match([time]);
  1301.     else if (func = 'read') return time_sub(_Match([time]), timer_start);
  1302. end;
  1303.  
  1304.  
  1305. #########################################################################
  1306. #    task            time_list(when)
  1307. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1308. #    Description:    This task converts a time descriptor to our 'time' format.
  1309. #    Parameters:        when:        time descriptor
  1310. #    Returns:        resulting time list
  1311. #    Examples:        now:= time_list();
  1312. #    Assumptions:    None
  1313. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1314. #    History:
  1315. #        ???        ???        Created
  1316. #    8/30/96        Marie    Added _Match
  1317. #########################################################################
  1318. task    time_list(when := _Match([time]))
  1319. begin
  1320.     return {when.s, (when.h mod 100), (when.h / 100), when.d, when.m, when.y, 1};
  1321. end;
  1322.  
  1323.  
  1324. #########################################################################
  1325. #    task            time_cmp(stop_time, start_time)
  1326. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1327. #    Description:    This task compares two times.
  1328. #    Parameters:        stop_time:    time descriptor or time list
  1329. #                    start_time:    time descriptor or time list
  1330. #    Returns:        +1 if the stop_time is greater than the start_time
  1331. #                    0 if they are equal
  1332. #                    -1 if the stop_time is less than the start_time.
  1333. #    Examples:        if (time_cmp(start_time, now)) timewarp();
  1334. #    Assumptions:    None
  1335. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1336. #    History:
  1337. #        ???        ???        Created
  1338. #########################################################################
  1339. task    time_cmp(stop_time, start_time)
  1340. begin
  1341.     if typeOf(stop_time) = 'descriptor' 
  1342.         return time_cmp(time_list(stop_time), start_time);
  1343.     if typeOf(start_time) = 'descriptor' 
  1344.         return time_cmp(stop_time, time_list(start_time));
  1345.  
  1346.     for i := 7 to 1 step -1 
  1347.     begin    
  1348.         if stop_time[i] > start_time[i] 
  1349.             return 1;
  1350.         else if stop_time[i] < start_time[i] 
  1351.             return -1;
  1352.     end;
  1353.     return 0;
  1354. end;
  1355.  
  1356.  
  1357. #########################################################################
  1358. #    task            time_neg(t)
  1359. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1360. #    Description:    Returns the negative of a time list.
  1361. #    Parameters:        t:        time list
  1362. #    Returns:        negative of the time list
  1363. #    Examples:        time_add(then, time_neg(now));
  1364. #    Assumptions:    None
  1365. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1366. #    History:
  1367. #        ???        ???        Created
  1368. #########################################################################
  1369. task    time_neg(t)
  1370. begin
  1371.     if typeOf(t) = 'descriptor' 
  1372.         return time_neg(time_list(t));
  1373.     sign := -1 * t[7];
  1374.     return replace(sign, 7, t);
  1375. end;
  1376.  
  1377. #########################################################################
  1378. #    task            time_add(a, b)
  1379. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1380. #    Description:    This task computes the sum of two times.
  1381. #    Parameters:        a:        time descriptor or time list
  1382. #                    b:        time descriptor or time list
  1383. #    Returns:        resulting time list
  1384. #    Examples:        time_add(then, now);
  1385. #    Assumptions:    None
  1386. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1387. #    History:
  1388. #        ???        ???        Created
  1389. #########################################################################
  1390. task    time_add(a, b)
  1391. begin
  1392.     if typeOf(a) = 'descriptor' 
  1393.         return time_add(time_list(a), b);
  1394.     if typeOf(b) = 'descriptor' 
  1395.         return time_add(a, time_list(b));
  1396.  
  1397.     (*Handle signs*)
  1398.  
  1399.     if a[7] > 0 
  1400.     begin
  1401.         if a[7] < 0         # a>0, b<0
  1402.             return time_sub(a, time_neg(b));
  1403.     end;
  1404.     else begin
  1405.         if b[7] > 0        # a<0, b>0
  1406.             return time_sub(b, time_neg(a));
  1407.         else            # a<0, b<0
  1408.             return time_neg(time_add(time_neg(a), time_neg(b)));
  1409.     end;
  1410.  
  1411.     (*If we've gotten to here then both times are positive*)
  1412.  
  1413.     save_trace := trace(false);
  1414.     sec := a[1] + b[1];
  1415.     carry := 0;
  1416.     if sec > 60 
  1417.     begin
  1418.         carry := 1;
  1419.         sec := sec - 60;
  1420.     end;
  1421.     
  1422.     min := a[2] + b[2] + carry;
  1423.     carry := 0;
  1424.     if min > 60 
  1425.     begin
  1426.         carry := 1;
  1427.         min := min - 60;
  1428.     end;
  1429.  
  1430.     hour := a[3] + b[3] + carry;
  1431.     carry := 0;
  1432.     if hour > 24 
  1433.     begin
  1434.         carry := 1;
  1435.         hour := hour - 24;
  1436.     end;
  1437.  
  1438.     day := a[4] + b[4] + carry;
  1439.     carry := 0;
  1440.  
  1441.     len := {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}[a[5]];
  1442.     if (a[5] = 2) and ((a[6] mod 4) = 0) len := len + 1;
  1443.  
  1444.     if day > len 
  1445.     begin
  1446.         carry := 1;
  1447.         day := day - len;
  1448.     end;
  1449.  
  1450.     month := a[5] + b[5] + carry;
  1451.     carry := 0;
  1452.     if month > 12 
  1453.     begin
  1454.         carry := 1;
  1455.         month := month - 12;
  1456.     end;
  1457.  
  1458.     year := a[6] + b[6] + carry;
  1459.     trace(save_trace);
  1460.  
  1461.     return {sec, min, hour, day, month, year, 1};
  1462. end;
  1463.  
  1464. #########################################################################
  1465. #    task            time_sub(stop_time, start_time)
  1466. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1467. #    Description:    This task computes the difference of two times.
  1468. #    Parameters:        stop_time:    time descriptor or time list
  1469. #                    start_time:    time descriptor or time list
  1470. #    Returns:        resulting time list
  1471. #    Examples:        time_sub(then, now);
  1472. #    Assumptions:    None
  1473. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1474. #    History:
  1475. #        ???        ???        Created
  1476. #########################################################################
  1477. task    time_sub(stop_time, start_time)
  1478. begin
  1479.     if typeOf(stop_time) = 'descriptor'
  1480.         return time_sub(time_list(stop_time), start_time);
  1481.     if typeOf(start_time) = 'descriptor'
  1482.         return time_sub(stop_time, time_list(start_time));
  1483.  
  1484.     (*Handle signs*)
  1485.  
  1486.     save_trace := trace(false);
  1487.     if stop_time[7] > 0 begin
  1488.         if start_time[7] < 0        # a>0, b<0
  1489.             return time_add(stop_time, time_neg(start_time));
  1490.     end;
  1491.     else begin
  1492.         if start_time[7] > 0        # a<0, b>0
  1493.             return time_neg(time_add(time_neg(stop_time), start_time));
  1494.         else                        # a<0, b<0
  1495.             return time_sub(time_neg(start_time), time_neg(stop_time));
  1496.     end;
  1497.  
  1498.     (*If we've gotten to here then both times are positive*)
  1499.  
  1500.     if time_cmp(stop_time, start_time) = -1
  1501.         return time_neg(time_sub(start_time, stop_time));
  1502.  
  1503.     start_s := start_time[1];
  1504.     start_min := start_time[2];
  1505.     start_h := start_time[3];
  1506.     start_d := start_time[4];
  1507.     start_m := start_time[5];
  1508.     start_y := start_time[6];
  1509.  
  1510.     stop_s := stop_time[1];
  1511.     stop_min := stop_time[2];
  1512.     stop_h := stop_time[3];
  1513.     stop_d := stop_time[4];
  1514.     stop_m := stop_time[5];
  1515.     stop_y := stop_time[6];
  1516.  
  1517.     if stop_s < start_s 
  1518.     begin
  1519.         stop_s := stop_s + 60;
  1520.         stop_min := stop_min - 1;
  1521.     end;
  1522.     stop_s := stop_s - start_s;
  1523.     
  1524.     if stop_min < start_min 
  1525.     begin
  1526.         stop_min := stop_min + 60;
  1527.         stop_h := stop_h - 1;
  1528.     end;
  1529.     stop_min := stop_min - start_min;
  1530.     
  1531.     if stop_h < start_h 
  1532.     begin
  1533.         stop_h := stop_h + 24;
  1534.         stop_d := stop_d - 1;
  1535.     end;
  1536.     stop_h := stop_h - start_h;
  1537.     
  1538.     if stop_d < start_d 
  1539.     begin
  1540.         month_index := stop_m - 1;
  1541.         if (month_index = 0) 
  1542.             month_index := 12;
  1543.         stop_d := stop_d + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}[month_index];
  1544.         if (month_index = 2) and ((stop_y mod 4) = 0) 
  1545.             stop_d := stop_d + 1;
  1546.         stop_m := stop_m - 1;
  1547.     end;
  1548.     stop_d := stop_d - start_d;
  1549.  
  1550.     if stop_m < start_m 
  1551.     begin
  1552.         stop_m := stop_m + 12;
  1553.         stop_y := stop_y - 1;
  1554.     end;
  1555.     stop_m := stop_m - start_m;
  1556.     
  1557.     stop_y := stop_y - start_y;
  1558.     trace(save_trace);
  1559.     return {stop_s, stop_min, stop_h, stop_d, stop_m, stop_y, 1};
  1560. end;
  1561.  
  1562. #########################################################################
  1563. #    task            time_str(t, format)
  1564. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1565. #    Description:    This task returns a string of the form "{hour}:{min}:{sec}",
  1566. #                    with numbers zero-padded on the left to two digits.
  1567. #    Parameters:        t:        time descriptor or time list
  1568. #                    format:    'm'    Give the minutes & seconds, "{min}:{sec}".
  1569. #                                This will return strings with > 60 minutes,
  1570. #                                if the hours are nonzero (e.g., "81:04").
  1571. #                            'h'    Full format -- give the hours, minutes, & seconds.
  1572. #    Returns:        resulting string
  1573. #    Examples:        println time_sub(now, 'h');
  1574. #    Assumptions:    None
  1575. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1576. #    History:
  1577. #        ???        ???        Created
  1578. #########################################################################
  1579. task    time_str(t, format := 'h')
  1580. begin
  1581.     if typeOf(t) = 'descriptor' 
  1582.         return time_str(time_list(t));
  1583.  
  1584.     save_trace := trace(false);
  1585.     s := t[1];
  1586.     m := t[2];
  1587.     h := t[3];
  1588.  
  1589.     str := "";
  1590.     if format = 'h' 
  1591.     begin
  1592.         if h < 10 str := str + "0";
  1593.         str := str + "{h}.";
  1594.     end;
  1595.     else m := m + 60 * h;
  1596.     
  1597.     if m < 10 
  1598.         str := str + "0";
  1599.     str := str + "{m}.";
  1600.     if s < 10 
  1601.         str := str + "0";
  1602.     str := str + "{s}";
  1603.     trace(save_trace);
  1604.     return str;
  1605. end;
  1606.  
  1607.  
  1608. #########################################################################
  1609. #    task            GetCheckSums(command, params)
  1610. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1611. #    Description:    Calls VUAid 2.0 to obtain checksums for all available
  1612. #                    bit depths.
  1613. #    Parameters:        command:    VUAid 2.0 service to request
  1614. #                    params:        List of parameters to send to VUAid 2.0
  1615. #    Returns:        Standard checksum list
  1616. #    Examples:        println GetCheckSums("CompareWindowRect", {10,10,30,30})
  1617. #    Assumptions:    Does not require VUAid.lib
  1618. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1619. #    History:
  1620. #        4/22/92    Jonathan Marsh        Original GetCheckSumList
  1621. #########################################################################
  1622. task    GetCheckSums(command:="CompareWindow", params := {})
  1623. begin
  1624.     checkSums:= {};
  1625.     oldDepth := VUAid2("GetDepth")[2];
  1626.     oldGrays := VUAid2("GetGray")[2];
  1627.     
  1628.     VUAid2("SetGray", 0);                #Get color checksums
  1629.     if VUAid2("GetGray")[2] = 0 
  1630.     begin
  1631.         for each bitdepth in {1, 2, 4, 8, 16, 32} 
  1632.         begin
  1633.             VUAid2("SetDepth", bitdepth);
  1634.             if VUAid2("GetDepth")[2] = bitDepth
  1635.                 if params = {}
  1636.                     checkSums:= checkSums + {VUAid2(command)[2]};
  1637.                 else checkSums:= checkSums + {VUAid2(command, params[1], params[2], params[3], params[4])[2]};
  1638.             else checkSums := checkSums + {'xxx'};
  1639.         end;
  1640.     end;    #getDepth = 0
  1641.     else 
  1642.         checkSums := {'xxx','xxx','xxx','xxx','xxx','xxx'};
  1643.  
  1644.     VUAid2("SetGray", 1);                #Get gray checksums
  1645.     if VUAid2("GetGray")[2] = 1 
  1646.     begin
  1647.         for each bitdepth in {2, 4, 8} 
  1648.         begin
  1649.             VUAid2("SetDepth", bitdepth);
  1650.             if VUAid2("GetDepth")[2] = bitDepth
  1651.                 if params = {}
  1652.                     checkSums:= checkSums + {VUAid2(command)[2]};
  1653.                 else checkSums:= checkSums + {VUAid2(command, params[1], params[2], params[3], params[4])[2]};
  1654.             else checkSums := checkSums + {'xxx'};
  1655.         end;
  1656.     end;    #getDepth = 0
  1657.     else
  1658.         checkSums := {'xxx','xxx','xxx','xxx','xxx','xxx'};
  1659.         
  1660.     if checkSums[2] = checkSums[7] and  checkSums[3] = checkSums[8] and checkSums[4] = checkSums[9] 
  1661.     begin
  1662.         checkSums := remove(9, checkSums);
  1663.         checkSums := remove(8, checkSums);
  1664.         checkSums := remove(7, checkSums);
  1665.     end;
  1666.     
  1667.     VUAid2("SetGray", oldGrays);
  1668.     VUAid2("SetDepth", oldDepth);
  1669.     return checkSums;
  1670. end;
  1671.  
  1672. #########################################################################
  1673. #    task            ComputerAidedSE(CAidedSE)
  1674. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1675. #    Description:    These routines are run from an rResult statement when
  1676. #                    Computer Aided Scripting Environment (CAidedSE) is enabled.
  1677. #                    They print out an entire testN, with a completed checksumList,
  1678. #                    instead of the normal error report, which can then be
  1679. #                    pasted directly into the script.  This should be used 
  1680. #                    after script development is complete to generate the
  1681. #                    final checksumList needed for successful execution on
  1682. #                    all bit-depths, color and grays.  In order to fully
  1683. #                    utilize this tool, it is suggested that the script be run
  1684. #                    on a color machine which is 16-bit and 24-bit capable.
  1685. #                    To turn on this function, call rSetCAidedSE(true).
  1686. #    Parameters:        CAidedSE: a list of information needed of format:
  1687. #                        {testN, {CheckSumLocation, VUAidStringToExecute} 
  1688. #                                [,{CheckSumLocation, VUAidStringToExecute}...]};
  1689. #                            testN:            the entire original test,
  1690. #                            checkSumLocation:    the item which should be replaced by a checksumList, and
  1691. #                            VUAidStringToExecute:    the string to send to VUAid.  
  1692. #                        NOTE: since a testN can conceivably incorporate multiple checksumlists,
  1693. #                            these can created by a third (or more) item shown above.
  1694. #                        If only a single VUAidCommand should be executed to return a single 
  1695. #                            expected item instead of a list, then put a negative if front of the
  1696. #                            checkSumLocation
  1697. #    Returns:        Nothing
  1698. #    Examples:        ComputerAidedSE(testN);
  1699. #    Assumptions:    That VUAid is correctly installed.  This does no VUAid error checking!
  1700. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1701. #    History:
  1702. #        06/09/92    Jason Marsh            Creation of ComputerAidedSE
  1703. #        4/19/94        Alan Winslow        Fixed VUAid2 call for a single item
  1704. #        4/29/94        Alan Winslow        Added ability to handle case where VUAidString does not require
  1705. #                                            a WindowRect (ex: "Balloon", for checksumming help balloons)
  1706. #########################################################################
  1707. task    ComputerAidedSE(CAidedSE)
  1708. begin
  1709. #CAidedSE := {testN, {CheckSumLocation, VUAidCommandString, VUAidParameterList} 
  1710. #        [,{CheckSumLocation, VUAidCommandString, VUAidParameterList}...]};
  1711.  
  1712.     testN := CAidedSE[1];
  1713.     for i := 2 to card CAidedSE 
  1714.     begin
  1715.         CheckSumLoc := CAidedSE[i][1];
  1716.         VUAidString := CAidedSE[i][2];
  1717.         VUAidParams := CAidedSE[i][3];
  1718.         VUP := VUAidParams;        # AMW Used below to shorten calling sequence
  1719.         if CheckSumLoc > 0                     #Get a checkSum List
  1720.         begin
  1721.             checkSumList := GetCheckSums(VUAidString, VUAidParams);
  1722.             testN := replace( checkSumList, CheckSumLoc, testN);
  1723.         end;
  1724.         else begin                            #just a single item    
  1725.             CheckSumLoc := CheckSumLoc * -1;
  1726.             if VUAidParams = {} or VUAidParams = undefined 
  1727.             temp := VUAid2(VUAidString)[2];                # AMW Example: "Balloon"
  1728.             else temp :=  VUAid2(VUAidString, VUP[1], VUP[2], VUP[3], VUP[4])[2];
  1729.             testN := replace( temp, CheckSumLoc, testN);
  1730.         end;
  1731.     end;
  1732.     
  1733.     println testN, ",";
  1734.     global gAddResult := {};            #Clear the Add result queue
  1735.     return true;
  1736. end;
  1737.  
  1738. #########################################################################
  1739. #    task            rSetCAidedSE(state)
  1740. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1741. #    Description:    Turn on or off ComputerAidedSE feature.
  1742. #    Parameters:        state:        turn ComputerAidedSE on (true) or off (false)
  1743. #    Returns:        Nothing
  1744. #    Examples:        rSetCAidedSE(true);
  1745. #    Assumptions:    None
  1746. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1747. #    History:
  1748. #        06/09/92    Jason Marsh            Creation of ComputerAidedSE
  1749. #########################################################################
  1750. task    rSetCAidedSE(state := true)
  1751. begin
  1752.     global gCAidedSEEnabled := state;
  1753. end;
  1754.